Skip to content

Conversation

@daaria-s
Copy link
Collaborator

This PR adds support for fractional palette indices (e.g., ColorPalette.Gray1.25) in ThemeColorPalette and updates parsing of fractional indices colors in BridgeColorPalette. Previously, only integer indices were supported.

Release notes

⚠️ Important Changes

  • Added new accessors to ThemeColorPalette for accessing fractional colors: grayOrNull(index, fractional), blueOrNull(index, fractional), etc.
    • Example usage: palette.grayOrNull(1, 25) will retrieve the color for Gray1.25.
  • Updated color parsing in BridgeColorPalette to support the new fractional index format when reading from the IDE environment.

New features

  • Added support for fractional indices in ThemeColorPalette

@daaria-s daaria-s added the Jewel label Jan 12, 2026
@daaria-s daaria-s requested a review from rock3r January 12, 2026 17:45
@daaria-s daaria-s self-assigned this Jan 12, 2026
public val purple: List<Color>,
public val teal: List<Color>,
public val rawMap: Map<String, Color>,
public val fractionalMap: Map<String, Color> = emptyMap(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would store all colours in just one map, given the keys are strings anyway, and have the code understand that non-fractional colours simply have a fractional part of zero. That way you can also look up grayOrNull(1, 0) to get Gray1, but more importantly, code does not have to access two separate maps to find a colour.

@daaria-s daaria-s force-pushed the daria.suvorova/JEWEL-1026 branch from 6fc01f5 to f560fa9 Compare January 13, 2026 10:55
- sf:PALETTE_KEY_PREFIX:java.lang.String
- <init>(java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.List,java.util.Map):V
- f:blue-vNxB06k(I):J
- f:blueOrNull-ijrfgN4(I):androidx.compose.ui.graphics.Color
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid breaking binary changes, we need to keep the old APIs, but deprecate them with DeprecationLevel.HIDDEN

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so that means that I should just add new methods (grayOrNull(Int, Int) etc) and also keep the old ones (grayOrNull(Int) etc)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for example:

@Deprecated("Use variant with fractional parameter", level = DeprecationLevel.HIDDEN)
public fun grayOrNull(index: Int): Color? = gray.getOrNull(index - 1)

public fun grayOrNull(index: Int, fractional: Int = 0): Color? =
    if (fractional == 0) {
        gray.getOrNull(index - 1)
    } else {
        rawMap["$PALETTE_KEY_PREFIX.Gray$index.$fractional"]
    }

The hidden symbols will still disappear from the dumps, but they will be included in the binary and invisible from code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image but I still get changes in api-dump like that - is it expected?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes — @faogustavo has helpfully listed a legend on how to read the dumps here:

* - marked with @ApiStatus.Experimental.
b - synthetic (as in binary visible). Members with both ACC_SYNTHETIC and ACC_BRIDGE are not included in the dump.
p - protected. Nothing for public because it's the default. private and package-private members are not included.
s - static.
@ - annotation.
e - enum.
f - final.
a - abstract.
c - class. Nothing for interface because it should be the default.

So, you're deprecating with HIDDEN level the existing blueOrNull(Int) — that's why it gets the b added to its existing f (DeprecationLevel.HIDDEN is a clever trick that (ab)uses the concept of a synthetic method in JVM bytecode). This is expected.

Next, you added blueOrNull(Int, Int = 0) where the second parameter has a default value; this is reflected in JVM bytecode as:

  1. A f:blueOrNull-6MYuD4A(I,I) with two Int parameters, both non-optional
  2. A f:blueOrNull-6MYuD4A$default(...) that is generated by the compiler to implement the default parameter behaviour
    • This is a synthetic static method that you can safely ignore:
      image

The weird -6MYuD4A suffixes are also added by the Kotlin Compiler; it's called mangling and you can read more about it here: https://ncorti.com/blog/name-mangling-in-kotlin

@rock3r
Copy link
Collaborator

rock3r commented Jan 19, 2026

Ready to merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants